import 'package:casdon/common/state/common_net_status.dart';
import 'package:casdon/core/extentions/string_validation.dart';
import 'package:casdon/core/logger/log.dart';
import 'package:casdon/core/network/business_exception.dart';
import 'package:casdon/core/utils/toast_utils.dart';
import 'package:casdon/modules/login/application/notifier/login_notifier.dart';
import 'package:casdon/modules/login/data/api/login_api.dart';
import 'package:casdon/modules/login/data/api/valide_code_type.dart';
import 'package:casdon/modules/login/domain/states/login_code_state.dart';
import 'package:casdon/modules/login/domain/states/regist_account_state.dart';
import 'package:casdon/modules/login/domain/usecases/check_account_usecase.dart';
import 'package:casdon/modules/login/domain/usecases/register_usecase.dart';
import 'package:casdon/modules/login/domain/usecases/send_emailCode_usecase.dart';
import 'package:casdon/modules/login/providers/login_code_provider.dart';
import 'package:casdon/modules/login/domain/usecases/send_sms_usecase.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

enum RegistAccountStep { check, sendCode, verifyCode, register }

class RegistAccountNotifier extends LoginNotifier<RegistAccountState> {
  RegistAccountStep step = RegistAccountStep.check;

  Future<void> sendCode({
    SendCodeSource source = SendCodeSource.accountPage,
  }) async {
    step = RegistAccountStep.sendCode;
    if (CommonNetStatus.loading == state.status) {
      return;
    }

    if (false == state.agreed) {
      setFailure(msg: "请先同意用户协议");
      return;
    }

    if (null == state.account) {
      setFailure(msg: "请先输入账号");
      return;
    }

    state = state.copyWith(
      source: source,
      errorCode: null,
      password: null,
      code: null,
      message: null,
      status: CommonNetStatus.loading,
    );

    if (state.account!.isPhoneNum()) {
      _sendSmsCode(state.account!);
    } else if (state.account!.isEmail()) {
      _sendEmailCode(state.account!);
    } else {
      setFailure(msg: "账号格式不正确");
    }
  }

  void updateAccount(String value) {
    step = RegistAccountStep.sendCode;
    state = state.copyWith(
      account: value,
      version: state.version,
      status: CommonNetStatus.idle,
    );
  }

  void updateCode(String value) {
    step = RegistAccountStep.verifyCode;
    state = state.copyWith(
      code: value,
      version: state.version,
      status: CommonNetStatus.idle,
    );
  }

  void updatePassword(String value) {
    step = RegistAccountStep.register;
    state = state.copyWith(
      password: value,
      version: state.version,
      status: CommonNetStatus.idle,
    );
  }

  Future<void> checkAccount() async {
    step = RegistAccountStep.check;
    state = state.copyWith(
      errorCode: null,
      password: null,
      code: null,
      message: null,
      status: CommonNetStatus.loading,
    );
    try {
      if (state.account == null || state.account!.trim().isEmpty) {
        setFailure(msg: "请输入账号");
        return;
      }
      if (state.account!.trim().isPhoneNum() == false &&
          state.account!.trim().isEmail() == false) {
        setFailure(msg: "账号格式错误");
        return;
      }
      final usecase = ref.read(checkAccountUsecaseProvider);
      final ret = await usecase.execute(userName: state.account!);
      setFailure(msg: "该账号已经注册，请直接登录");
    } on BusinessException catch (e) {
      if (e.code == "10003") {
        setSuccess("");
        await sendCode();
      } else {
        ToastUtil.show(e.msg);
      }
      rethrow;
    }
  }

  void _sendSmsCode(String phone) async {
    try {
      SendSmsUsecase sendSmsUsecase = ref.read(sendSmsUsecaseProvider);
      final ret = await sendSmsUsecase.execute(phone, ValideCodeType.register);
      if (ret.success == true) {
        setSuccess("发送验证码成功");
      } else {
        setFailure(msg: ret.message ?? "发送验证码失败");
      }
    } catch (e) {
      setFailure(msg: getErrorMessage(e));
    }
  }

  void _sendEmailCode(String email) async {
    try {
      SendEmailcodeUsecase sendEmailcodeUsecase = ref.read(
        sendEmailcodeProvider,
      );
      final ret = await sendEmailcodeUsecase.execute(
        email,
        ValideCodeType.register,
      );
      if (ret == true) {
        setSuccess("发送验证码成功");
      } else {
        setFailure(msg: "发送验证码失败");
      }
    } catch (e) {
      setFailure(msg: getErrorMessage(e));
    }
  }

  // 注册
  Future<void> register() async {
    state = state.copyWith(
      errorCode: null,
      message: null,
      status: CommonNetStatus.loading,
    );
    step = RegistAccountStep.register;
    var grantType = LoginGrantType.sms.name;
    if (state.account!.isEmail()) {
      grantType = LoginGrantType.email.name;
    }
    if (state.account == null || state.account!.isEmpty) {
      setFailure(msg: "账号不能为空");
      return;
    }
    if (state.password == null || state.password!.isEmpty) {
      setFailure(msg: "密码不能为空");
      return;
    }
    try {
      final usecase = ref.read(registerUsecaseProvider);

      final _ = await usecase.execute(
        userName: state.account!.trim(),
        grantType: grantType,
        password: state.password!.trim(),
      );
      Log.i("注册成功，account = ${state.account}");

      setSuccess("注册成功");
    } on BusinessException catch (e) {
      setFailure(errorCode: e.code, msg: e.msg);
    } catch (e) {
      setFailure(msg: "注册失败，请稍后再试！");
    }
  }

  Future<void> verifyCode() async {
    if (state.status == CommonNetStatus.loading) {
      return;
    }
    if (state.account == null || state.code == null) {
      setFailure(msg: "账号或密码为空");
      return;
    }
    step = RegistAccountStep.verifyCode;
    state = state.copyWith(
      status: CommonNetStatus.loading,
      message: null,
      errorCode: null,
      password: null,
    );

    try {
      final verifyUsecase = ref.read(verifyOtpUsecaseProvider);
      final ret = await verifyUsecase.execute(
        state.account!,
        state.code!,
        ValideCodeType.register,
      );

      if (ret == true) {
        setSuccess("验证码正确");
      } else {
        setFailure(msg: "验证码错误");
      }
    } on BusinessException catch (e) {
      setFailure(errorCode: e.code, msg: e.msg);
    } catch (e) {
      setFailure(msg: "验证码校验失败");
      Log.e("验证码校验失败", e.toString(), StackTrace.current);
    }
  }

  @override
  RegistAccountState build() {
    ref.onDispose(() {
      Log.d("已经销毁：RegistAccountNotifier");
    });
    return RegistAccountState.initial();
  }
}

final registerAccountProvider =
    NotifierProvider.autoDispose<RegistAccountNotifier, RegistAccountState>(
      () => RegistAccountNotifier(),
    );
